/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package it.polimi.meteocal.control;

import it.polimi.meteocal.entity.Event;
import it.polimi.meteocal.entity.InvitedList;
import it.polimi.meteocal.entity.InvitedListPK;
import it.polimi.meteocal.entity.Message;
import it.polimi.meteocal.entity.User;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class EventManager {

    @PersistenceContext
    private EntityManager em;
    @EJB
    private UserManager um;
    @EJB
    private ForecastManager fm;
    @EJB
    private MessageManager mm;
    @EJB
    private InvitationManager im;

    private Collection<Event> eventCollection;

    /**
     * persist an event in the data base, check if the forecast should be
     * created and if there are invited send a message to all
     *
     * @param event
     * @param invitedUsers
     */
    public void createEvent(Event event, ArrayList<String> invitedUsers) {
        System.out.println("****************CREATEEVENT*************");
        event.setDeleted(Boolean.FALSE);
        event.setAuthor(um.getLoggedUser());
        em.persist(event);
        em.flush();
        if (event.getEndDate().get(Calendar.DAY_OF_YEAR) == event.getStartDate().get(Calendar.DAY_OF_YEAR) && event.getOutdoor()) {
            if (!fm.checkExistForecast(event)) {
                fm.createForecast(event);
            }
        }
        if (!invitedUsers.isEmpty()) {
            Message message = mm.createMessage(event, 2);
            im.addInvitation(event, invitedUsers);
            mm.addInvitedMessage(event, invitedUsers, message);
        }
    }

    /**
     * persist the modification of the event in the data base, check if the
     * forecast is still consistent with the new information or if should be
     * modified. If there were old invited that already partecipate a message of
     * modification is created, if there are new invited a message of invitation
     * is created
     *
     * @param event
     * @param invitedUsers
     * @param oldInvited
     */
    public void modifyEvent(Event event, ArrayList<String> invitedUsers, int oldInvited) {
        em.merge(event);
        em.flush();
        event = fm.consictency(event);
        if (event.getEndDate().get(Calendar.DAY_OF_YEAR) == event.getStartDate().get(Calendar.DAY_OF_YEAR) && event.getOutdoor()) {
            if (fm.checkModifyForecast(event)) {
                if (!fm.checkExistForecast(event)) {
                    fm.createForecast(event);
                }
            }
        }
        if (oldInvited != 0) {
            Message message = mm.createMessage(event, 1);
            ArrayList<String> iu = new ArrayList<>();
            for (String user : invitedUsers.subList(0, oldInvited)) {
                if (im.partecipate(event, user)) {
                    iu.add(user);
                }
            }
            mm.addInvitedMessage(event, iu, message);
        }
        if (invitedUsers.size() > oldInvited) {
            Message message = mm.createMessage(event, 2);
            im.addInvitation(event, invitedUsers.subList(oldInvited, invitedUsers.size()));
            mm.addInvitedMessage(event, invitedUsers.subList(oldInvited, invitedUsers.size()), message);
        }
    }

    /**
     *
     * @return the event of the logged user
     */
    public Collection<Event> getUserEvent() {
        System.out.println("**********GETTING_USER_EVENT***********");
        em.getEntityManagerFactory().getCache().evictAll();
        eventCollection = um.getLoggedUser().getEventCollection();
        Collection<InvitedList> invitedListCollection = um.getLoggedUser().getInvitedListCollection();
        for (InvitedList invitedList : invitedListCollection) {
            if (invitedList.getPartecipation() != null) {
                if (invitedList.getPartecipation()) {
                    eventCollection.add(invitedList.getEvent());
                }
            }
        }
        Collection<Event> eventCol = new ArrayList<>();
        for (Event e : eventCollection) {
            if (!e.getDeleted()) {
                eventCol.add(e);
            }
        }
        return eventCol;
    }

    /**
     *
     * @param user
     * @return the event of a specific user
     */
    public Collection<Event> getUserEvent(String user) {
        System.out.println("**********GETTING_USER_EVENT***********" + user);
        em.getEntityManagerFactory().getCache().evictAll();
        User userEntity = em.find(User.class, user);
        if (userEntity.getPublicCalendar()) {
            eventCollection = userEntity.getEventCollection();
            Collection<InvitedList> invitedListCollection = userEntity.getInvitedListCollection();
            for (InvitedList invitedList : invitedListCollection) {
                eventCollection.add(invitedList.getEvent());
            }
            Collection<Event> eventCol = new ArrayList<>();
            for (Event e : eventCollection) {
                if (!e.getDeleted()) {
                    eventCol.add(e);
                }
            }
            return eventCol;
        } else {
            return null;
        }
    }

    /**
     *
     * @param selectedEvent
     * @return the event from the data base
     */
    public Event findByID(String selectedEvent) {
        em.find(Event.class, Long.valueOf(selectedEvent));
        System.out.println(em.find(Event.class, Long.valueOf(selectedEvent)).getName());
        return em.find(Event.class, Long.valueOf(selectedEvent));
    }

    /**
     * set the boolen of delete for the message and create a message for each
     * invited user that partecipate to the event
     *
     * @param event
     */
    public void delete(Event event) {
        System.out.println("*******************DELETE**************");
        event.setDeleted(Boolean.TRUE);
        em.merge(event);
        em.flush();
        if (!event.getInvitedListCollection().isEmpty()) {
            Message message = mm.createMessage(event, 0);
            ArrayList<String> invitedUser = new ArrayList<>();
            for (InvitedList i : event.getInvitedListCollection()) {
                if (i.getPartecipation() != null) {
                    if (i.getPartecipation()) {
                        invitedUser.add(i.getUser().getEmail());
                    }
                }
            }
            mm.addInvitedMessage(event, invitedUser, message);
        }
    }

    /**
     *
     * @param selectedEvent
     * @return true if the user is invited to the event, false otherwise
     */
    public boolean invited(String selectedEvent) {
        InvitedListPK ilpk = new InvitedListPK();
        ilpk.setEvent(Long.valueOf(selectedEvent));
        ilpk.setUser(um.getLoggedUser().getEmail());
        InvitedList find = em.find(InvitedList.class, ilpk);
        if (find == null) {
            return Boolean.FALSE;
        } else {
            return Boolean.TRUE;
        }
    }

}
